using System.Collections.Generic;
using System.IO;
using BizHawk.Emulation.Common;

namespace BizHawk.Client.Common
{
	public interface IStateManager : IDisposable
	{
		IStateManagerSettings Settings { get; }

		/// <summary>
		/// Requests that the current emulator state be captured
		/// Unless force is true, the state may or may not be captured depending on the logic employed by "green-zone" management
		/// </summary>
		/// <param name="force">If true, the state will be temporarily captured. If it would not have otherwise been captured, it may be deleted as soon as another state is force captured.</param>
		void Capture(int frame, IStatable source, bool force = false);

		/// <summary>
		/// Tell the state manager we no longer wish to reserve the state for the given frame.
		/// </summary>
		void Unreserve(int frame);

		bool HasState(int frame);

		/// <summary>
		/// Clears out all savestates after the given frame number
		/// </summary>
		bool InvalidateAfter(int frame);

		// Remove all states, but not the frame 0 state
		void Clear();

		/// <summary>
		/// Get a nearby state.  The returned frame must be less than or equal to the passed frame.
		/// This may not fail; the StateManager strongly holds a frame 0 state to ensure there's always a possible result.
		/// </summary>
		/// <returns>This stream may be consumed only once, and before any other calls to statemanager occur</returns>
		KeyValuePair<int, Stream> GetStateClosestToFrame(int frame);

		/// <value>the total number of states currently held by the state manager</value>
		int Count { get; }

		/// <value>the most recent frame number that the state manager possesses</value>
		int Last { get; }

		/// <summary>
		/// Updates the internal state saving logic settings
		/// May create a new state manager
		/// </summary>
		IStateManager UpdateSettings(IStateManagerSettings settings, bool keepOldStates = false);

		/// <summary>
		/// Serializes the current state of the instance for persisting to disk
		/// </summary>
		void SaveStateHistory(BinaryWriter bw);

		/// <summary>
		/// Deserializes the state of the instance that was persisted to disk
		/// </summary>
		void LoadStateHistory(BinaryReader br);

		/// <summary>
		/// Enables the instance to be used. An instance of <see cref="IStateManager"/> should not
		/// be useable until this method is called
		/// </summary>
		void Engage(byte[] frameZeroState);
	}
}
